package com.pyue.eam.admin.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Week;
import cn.hutool.core.util.StrUtil;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.util.StringUtils;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class EamDateUtil {

    // 时间元素
    private static final String YEAR = "year";
    private static final String MONTH = "month";
    private static final String WEEK = "week";
    private static final String DAY = "day";
    private static final String HOUR = "hour";
    private static final String MINUTE = "minute";
    private static final String SECOND = "second";
    // 星期元素
    private static final String MONDAY = "MONDAY";// 星期一
    private static final String TUESDAY = "TUESDAY";// 星期二
    private static final String WEDNESDAY = "WEDNESDAY";// 星期三
    private static final String THURSDAY = "THURSDAY";// 星期四
    private static final String FRIDAY = "FRIDAY";// 星期五
    private static final String SATURDAY = "SATURDAY";// 星期六
    private static final String SUNDAY = "SUNDAY";// 星期日
    // 时间格式
    public static final String YYMMDD = "YYMMdd";
    public static final String TIME = "HHmmss";
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    public static final String yyMMddHHmmss = "yyMMddHHmmss";
    private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy" +
            "/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    // 时间格式化器
    public static final DateTimeFormatter yyyyMMddHHmm_EN = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
    public static final DateTimeFormatter YYMMDDHHMMSS_EN = DateTimeFormatter.ofPattern(yyMMddHHmmss);
    public static final DateTimeFormatter YY_MM_DD_HHMMSS = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
    public static final DateTimeFormatter YYYYMMDD_EN = DateTimeFormatter.ofPattern(YYYY_MM_DD);


    /**
     * 将指定的时间字符串格式化为日期
     *
     * @param dateStr
     * @return
     */
    public static LocalDate parseYMD(String dateStr) {
        if (StrUtil.isBlank(dateStr)) {
            return null;
        }
        return LocalDate.parse(dateStr, YYYYMMDD_EN);
    }

    /**
     * 取时间对应的年月
     *
     * @param dateStr eg: 2021-02-29
     * @return 2021-02
     */
    public static String parseYMStr(String dateStr) {
        if (StrUtil.isBlank(dateStr)) {
            return null;
        }
        LocalDate localDate = parseStrToLocalDate(dateStr);
        return YearMonth.of(localDate.getYear(), localDate.getMonthValue()).toString();
    }

    /**
     * 获取当前日期的节点时间（年，月，周，日，时，分，秒）
     *
     * @param node 日期中的节点元素（年，月，周，日，时，分，秒） 节点数字，如创建此方法的时间：年 2019，月 3，日 30，周 6
     * @author zero 2019/03/30 星期六
     */
    public static Integer getNodeTime(String node) {
        LocalDateTime today = LocalDateTime.now();
        return getNodeTime(today, node);
    }

    public static Integer getNodeTime(LocalDateTime dateTime, String node) {
        Integer resultNode;
        switch (node) {
            case YEAR:
                resultNode = dateTime.getYear();
                break;
            case MONTH:
                resultNode = dateTime.getMonthValue();
                break;
            case WEEK:
                resultNode = transformWeekEN2Num(String.valueOf(dateTime.getDayOfWeek()));
                break;
            case DAY:
                resultNode = dateTime.getDayOfMonth();
                break;
            case HOUR:
                resultNode = dateTime.getHour();
                break;
            case MINUTE:
                resultNode = dateTime.getMinute();
                break;
            case SECOND:
                resultNode = dateTime.getSecond();
                break;
            default:
                // 当前日期是当前年的第几天。例如：2019/1/3是2019年的第三天
                resultNode = dateTime.getDayOfYear();
                break;
        }
        return resultNode;
    }

    /**
     * 将英文星期转换成数字
     *
     * @param enWeek 英文星期 int，如果数字小于0，则检查，看是否输入错误 or 入参为null
     * @author zero 2019/03/30
     */
    public static int transformWeekEN2Num(String enWeek) {
        if (MONDAY.equals(enWeek)) {
            return 1;
        } else if (TUESDAY.equals(enWeek)) {
            return 2;
        } else if (WEDNESDAY.equals(enWeek)) {
            return 3;
        } else if (THURSDAY.equals(enWeek)) {
            return 4;
        } else if (FRIDAY.equals(enWeek)) {
            return 5;
        } else if (SATURDAY.equals(enWeek)) {
            return 6;
        } else if (SUNDAY.equals(enWeek)) {
            return 7;
        } else {
            return -1;
        }
    }

    /**
     * 获取与当前日期相距num个之后（之前）的日期<br>
     * <ul>
     * 比如当前时间为：2019-03-30 10:20:30的格式日期
     * <li>node="hour",num=5L:2019-03-30 15:20:30</li>
     * <li>node="day",num=1L:2019-03-31 10:20:30</li>
     * <li>node="year",num=1L:2020-03-30 10:20:30</li>
     * </ul>
     *
     * @param dtf      格式化当前时间格式（dtf = yyyyMMddHHmmss_EN）
     * @param nodeName 节点元素（“year”,"month","week","day","huor","minute","second"）
     * @param num      （+：之后，-：之前） 之后之前的日期
     * @author zero 2019/03/30
     */
    public static String getAfterOrPreNowTimePlus(DateTimeFormatter dtf, String nodeName, Long num) {
        LocalDateTime now = LocalDateTime.now();
        if (HOUR.equals(nodeName)) {
            return now.plusHours(num).format(dtf);
        } else if (DAY.equals(nodeName)) {
            return now.plusDays(num).format(dtf);
        } else if (WEEK.equals(nodeName)) {
            return now.plusWeeks(num).format(dtf);
        } else if (MONTH.equals(nodeName)) {
            return now.plusMonths(num).format(dtf);
        } else if (YEAR.equals(nodeName)) {
            return now.plusYears(num).format(dtf);
        } else if (MINUTE.equals(nodeName)) {
            return now.plusMinutes(num).format(dtf);
        } else if (SECOND.equals(nodeName)) {
            return now.plusSeconds(num).format(dtf);
        } else {
            return "Node is Error!";
        }
    }

    /**
     * 检查重复事件，比如生日。TODO This is a example.
     */
    public static boolean isBirthday(int month, int dayOfMonth) {
        MonthDay birthDay = MonthDay.of(month, dayOfMonth);
        // MonthDay只存储了月、日。
        MonthDay curMonthDay = MonthDay.from(LocalDate.now());
        return birthDay.equals(curMonthDay);
    }

    /**
     * 获取指定时间范围 eg:[2021-09-28, 2021-09-29, 2021-09-30]
     *
     * @param startDate
     * @param endDate
     * @param type      1->天  2->月
     */
    public static List<LocalDate> getPieDateRange(LocalDate startDate, LocalDate endDate, Integer type) {
        List<LocalDate> result = Lists.newArrayList();
        while (startDate.isBefore(endDate) || startDate.isEqual(endDate)) {
            result.add(startDate);
            if (type == 1) {
                startDate = startDate.plusDays(1);
            }
            if (type == 2) {
                startDate = startDate.plusMonths(1);
            }
        }
        return result;
    }

    /**
     * 切割日期。按照周期切割成小段日期段。例如： <br>
     *
     * @param startDate 开始日期（yyyy-MM-dd）
     * @param endDate   结束日期（yyyy-MM-dd）
     * @param period    周期（天，周，月，年） 切割之后的日期集合
     * @author zero 2019/04/02
     * @example <li>startDate="2019-02-28",endDate="2019-03-05",period="day"</li>
     * <li>结果为：[2019-02-28, 2019-03-01, 2019-03-02, 2019-03-03, 2019-03-04, 2019-03-05]</li><br>
     * <li>startDate="2019-02-28",endDate="2019-03-25",period="week"</li>
     * <li>结果为：[2019-02-28,2019-03-06, 2019-03-07,2019-03-13, 2019-03-14,2019-03-20,
     * 2019-03-21,2019-03-25]</li><br>
     * <li>startDate="2019-02-28",endDate="2019-05-25",period="month"</li>
     * <li>结果为：[2019-02-28,2019-02-28, 2019-03-01,2019-03-31, 2019-04-01,2019-04-30,
     * 2019-05-01,2019-05-25]</li><br>
     * <li>startDate="2019-02-28",endDate="2020-05-25",period="year"</li>
     * <li>结果为：[2019-02-28,2019-12-31, 2020-01-01,2020-05-25]</li><br>
     */
    public static List<String> getPieDateRange(String startDate, String endDate, String period) {
        List<String> result = Lists.newArrayList();
        LocalDate end = parseStrToLocalDate(endDate);
        LocalDate start = parseStrToLocalDate(startDate);
        LocalDate tmp = start;
        switch (period) {
            case DAY:
                while (start.isBefore(end) || start.isEqual(end)) {
                    result.add(start.toString());
                    start = start.plusDays(1);
                }
                break;
            case WEEK:
                while (tmp.isBefore(end) || tmp.isEqual(end)) {
                    if (tmp.plusDays(6).isAfter(end)) {
                        result.add(tmp + "," + end);
                    } else {
                        result.add(tmp + "," + tmp.plusDays(6));
                    }
                    tmp = tmp.plusDays(7);
                }
                break;
            case MONTH:
                while (tmp.isBefore(end) || tmp.isEqual(end)) {
                    LocalDate lastDayOfMonth = tmp.with(TemporalAdjusters.lastDayOfMonth());
                    if (lastDayOfMonth.isAfter(end)) {
                        result.add(tmp + "," + end);
                    } else {
                        result.add(tmp + "," + lastDayOfMonth);
                    }
                    tmp = lastDayOfMonth.plusDays(1);
                }
                break;
            case YEAR:
                while (tmp.isBefore(end) || tmp.isEqual(end)) {
                    LocalDate lastDayOfYear = tmp.with(TemporalAdjusters.lastDayOfYear());
                    if (lastDayOfYear.isAfter(end)) {
                        result.add(tmp + "," + end);
                    } else {
                        result.add(tmp + "," + lastDayOfYear);
                    }
                    tmp = lastDayOfYear.plusDays(1);
                }
                break;
            default:
                break;
        }
        return result;
    }

    /**
     * 指定日期月的最后一天（yyyy-MM-dd）
     *
     * @param curDate     日期格式（yyyy-MM-dd）
     * @param firstOrLast true：第一天，false：最后一天
     * @author zero 2019/04/13
     */
    public static String getLastDayOfMonth(String curDate, boolean firstOrLast) {
        if (firstOrLast) {
            return LocalDate.parse(curDate, YYYYMMDD_EN).with(TemporalAdjusters.firstDayOfMonth()).toString();
        } else {
            return LocalDate.parse(curDate, YYYYMMDD_EN).with(TemporalAdjusters.lastDayOfMonth()).toString();
        }
    }

    /**
     * 获取年
     */
    public static int getYear() {
        return LocalTime.now().get(ChronoField.YEAR);
    }

    /**
     * 获取月份
     */
    public static int getMonth() {
        return LocalTime.now().get(ChronoField.MONTH_OF_YEAR);
    }

    /**
     * 格式化日期为字符串
     *
     * @param date    date
     * @param pattern 格式 日期字符串
     */
    public static String format(Date date, String pattern) {
        Instant instant = date.toInstant();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 解析字符串日期为Date
     *
     * @param dateStr 日期字符串
     * @param pattern 格式 Date
     */
    public static Date parse(String dateStr, String pattern) {
        LocalDateTime localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    /**
     * 返回当天的起始时间
     */
    public static Date getStartTime() {
        LocalDateTime now = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        return localDateTime2Date(now);
    }

    /**
     * 返回当天的结束时间
     */
    public static Date getEndTime() {
        LocalDateTime now = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).withNano(999);
        return localDateTime2Date(now);
    }

    /**
     * LocalDate类型转为Date
     *
     * @param localDate LocalDate object Date object
     */
    public static Date localDate2Date(LocalDate localDate) {
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * LocalDateTime类型转为Date
     *
     * @param localDateTime LocalDateTime object Date object
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 查询前一年最后一个月第一天
     *
     * @param pattern 格式，默认格式yyyyMMdd 20190101
     */
    public static String getLastMonthFirstDayOfPreviousYear(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).withMonth(12).withDayOfMonth(1);

        if (StrUtil.isBlank(pattern)) {
            pattern = "yyyyMMdd";
        }

        return format(localDateTime2Date(localDateTime), pattern);
    }

    /**
     * 格式化为当前月份
     */
    public static String dateFormatMonth(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        return sdf.format(date);
    }

    /**
     * 格式化为当前年份
     */
    public static String dateFormatYear(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        return sdf.format(date);
    }

    /**
     * 传入具体日期 ，返回具体日期减一个月。
     *
     * @param date 日期(2014-04-20) 2014-03-20
     */
    public static String subMonth(String date) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date dt = sdf.parse(date);
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);

        rightNow.add(Calendar.MONTH, -1);
        Date dt1 = rightNow.getTime();
        String reStr = sdf.format(dt1);

        return reStr;
    }

    /**
     * 获取月末最后一天
     */
    private static String getMonthMaxDay(String sDate) {
        SimpleDateFormat sdf_full = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        Date date = null;
        try {
            date = sdf_full.parse(sDate + "-01");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        cal.setTime(date);
        int last = cal.getActualMaximum(Calendar.DATE);
        return String.valueOf(last);
    }

    // 判断是否是月末
    public static boolean isMonthEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (cal.get(Calendar.DATE) == cal.getActualMaximum(Calendar.DAY_OF_MONTH)) {
            return Boolean.TRUE;
        } else {
            return false;
        }
    }

    /***
     * 日期减一天、加一天
     * 传入类型 pre：日期减一天，next：日期加一天
     */
    public static String checkOption(String option, String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cl = Calendar.getInstance();
        Date date = null;

        try {
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        cl.setTime(date);
        if ("pre".equals(option)) {
            // 时间减一天
            cl.add(Calendar.DAY_OF_MONTH, -1);

        } else if ("next".equals(option)) {
            // 时间加一天
            cl.add(Calendar.DAY_OF_YEAR, 1);
        } else {
            // do nothing
        }
        date = cl.getTime();
        return sdf.format(date);
    }

    /**
     * 传一个时间字符串 只取月和日
     */
    public static String getMmDdByDateStr(String dateStr) {
        return StrUtil.isBlank(dateStr) ? "" : dateStr.substring(dateStr.length() - 5);
    }

    /**
     * 获取当前年月日字符串
     * eg:20221113
     */
    public static String getCurrentYMD() {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return sdf.format(calendar.getTime());
    }

    public static LocalDate dateTimeToLocalDate(DateTime dateTime) {
        if (dateTime == null) {
            return null;
        }
        return LocalDate.of(dateTime.year(), dateTime.month() + 1, dateTime.dayOfMonth());
    }

    public static LocalDateTime dateTimeToLocalDateTime(DateTime dateTime) {
        if (dateTime == null) {
            return null;
        }
        return LocalDateTime.of(dateTime.year(), dateTime.month() + 1, dateTime.dayOfMonth(), dateTime.hour(true), dateTime.minute(), dateTime.second());
    }

    public static String parseYearMonthToYMD(String dateStr) {
        if (StrUtil.isBlank(dateStr)) {
            return null;
        } else if (StrUtil.length(dateStr) <= 7) {
            dateStr = StrUtil.replace(dateStr, ".", "-") + "-01";
        }
        return parseStrToLocalDate(dateStr).toString();
    }

    public static LocalDate parseStrToLocalDate(String dateStr) {
        if (StrUtil.isBlank(dateStr)) {
            return null;
        }
        if (StrUtil.length(dateStr) == 7) {
            dateStr = dateStr + "-01";
        }
        return dateTimeToLocalDate(DateUtil.parse(dateStr));
    }

    public static String parseLocalTimeByFormat(LocalDateTime localDateTime, DateTimeFormatter formatter) {
        return localDateTime != null ? localDateTime.format(formatter) : "";
    }

    public static String parseToYYMMddHHmmssStr(LocalDateTime localDateTime) {
        return localDateTime != null ? localDateTime.format(YYMMDDHHMMSS_EN) : "";
    }

    public static LocalDateTime parseStrToLocalDateTime(String dateStr) {
        return StringUtils.hasLength(dateStr) ? dateTimeToLocalDateTime(DateUtil.parse(dateStr)) : null;
    }

    /**
     * @param yearMonth 年月 该年月的第一天
     */
    public static String yearMonthToLocalDateStr(YearMonth yearMonth) {
        if (yearMonth != null) {
            return LocalDate.of(yearMonth.getYear(), yearMonth.getMonth(), 1).toString();
        }
        return null;
    }

    /**
     * @param localDate
     * @param hour
     * @param minute    拼装时间
     */
    public static LocalDateTime assemblyToLocalTime(LocalDate localDate, String hour, String minute) {
        return LocalDateTime.of(localDate, LocalTime.of(Convert.toInt(hour), Convert.toInt(minute)));
    }

    /**
     * @param size 前n个月 前n个月的yyyy-MM集合
     */
    public static List<String> getDateList(LocalDate localDate, Integer size) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
        List<String> stringList = CollUtil.newArrayList();

        AtomicInteger atomicInteger = new AtomicInteger(-size);
        for (int i = 0; i < size; i++) {
            stringList.add(localDate.plusMonths(atomicInteger.addAndGet(1)).format(dateTimeFormatter));
        }
        return stringList;
    }

    /**
     * 排除周六周日后两个时间间隔
     */
    public static long betweenDayExcludeWeekend(LocalDate startDate, LocalDate endDate) {
        if (startDate == null || endDate == null || endDate.isBefore(startDate)) {
            return 0;
        }

        List<LocalDate> pieDateRange = getPieDateRange(startDate, endDate, 1);
        long count = pieDateRange.stream().filter(e -> !DateUtil.isWeekend(localDate2Date(e))).count();
        return Convert.toInt(count, 0);
    }


    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     */
    public static String getDate() {
        return dateTimeNow(YYYY_MM_DD);
    }

    public static final String dateTimeNow(final String format) {
        return parseDateToStr(format, new Date());
    }

    public static final String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static final String datePath() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return DateUtils.parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }

    /**
     * 相差时间间隔-正数
     */
    public static long betweenLocalDateTime(LocalDateTime startTime, LocalDateTime endTime, DateUnit dateUnit) {
        if (startTime == null || endTime == null || dateUnit == null) {
            return 0;
        }
        return Convert.toInt(DateUtil.between(localDateTime2Date(startTime), localDateTime2Date(endTime), dateUnit), 0);
    }

    /**
     * 相差时间间隔-按开始和结束时间区分正负
     */
    public static long betweenLocalDateTimeFlag(LocalDateTime startTime, LocalDateTime endTime, DateUnit dateUnit) {
        long betDay = betweenLocalDateTime(startTime, endTime, dateUnit);
        if (betDay != 0 && endTime.isBefore(startTime)) {
            return 0 - betDay;
        }
        return betDay;
    }

    /**
     * 获取该月份指定周日
     */
    public static List<LocalDate> sunDayListByMonth(LocalDate localDate) {
        return dayListByMonth(localDate, Week.SUNDAY.getValue());
    }

    /**
     * 获取该月份指定周几
     *
     * @param localDate 当前月份
     * @param dayOfWeek 周几
     */
    public static List<LocalDate> dayListByMonth(LocalDate localDate, Integer dayOfWeek) {
        Date date = localDate2Date(localDate);
        DateTime beginOfMonth = DateUtil.beginOfMonth(date);
        DateTime endOfMonth = DateUtil.endOfMonth(date);

        return getPieDateRange(dateTimeToLocalDate(beginOfMonth), dateTimeToLocalDate(endOfMonth), 1).parallelStream().filter(e -> DateUtil.dayOfWeek(localDate2Date(e)) == dayOfWeek).collect(Collectors.toList());
    }

    /**
     * 一组时间段 求不重叠的分钟累加
     */
    public static long getMinuteSum(List<LocalDateTime> startTimes, List<LocalDateTime> endTimes) {
        if (startTimes.size() != endTimes.size()) {
            throw new RuntimeException("时间段不匹配");
        }
        long sum = 0;
        for (int i = 0; i < startTimes.size(); i++) {
            LocalDateTime startTime = startTimes.get(i);
            LocalDateTime endTime = endTimes.get(i);
            sum += betweenLocalDateTime(startTime, endTime, DateUnit.MINUTE);
        }
        return sum;
    }

    /**
     * yearmonth 转换 localdate
     *
     * @param yearMonth 年月
     * @return 如果为空，返回当前月份
     * 如果不为空，返回当月第一天
     */
    public static LocalDate yearMonthToLocalDateDefaultNow(YearMonth yearMonth) {
        if (yearMonth == null) {
            return LocalDate.now();
        }
        return LocalDate.of(yearMonth.getYear(), yearMonth.getMonth(), 1);
    }
}

